using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;

namespace BattleTetrixReloaded
{
    public class tet_main : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Random random;
        public static Texture2D background, background_black, blockTexture, boardBackground, nextPieceBackground;
        public static Texture2D[] nextPieces, bonuses;
        public static Vector2 boardPosition;
        Vector2 baseScreenSize = new Vector2(1920, 1080); 
        public static List<tet_bonus> bonusQueue;
        char[] shapes = { 'i', 'j', 'l', 'o', 's', 'z', 't' };            
        public static SpriteFont testFont;                       
        public static int gameState = tet_constants.STATE_TITLE;        
        private Matrix SpriteScale;
        tet_game_loop gameLoop;
        tet_net_server server = null;
        tet_net_client client = null;
        bool isHost;
        public static bool isReady = false;
        KeyboardState oldKeyboardState;

        public tet_main()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            Window.Title = "Battle Tetrix Reloaded HD - ALPHA";
        }      
 
        protected override void Initialize()
        {
            base.Initialize();
            IsMouseVisible = true;
            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferredBackBufferWidth = 1280;
            graphics.ApplyChanges();

            float screenscale = (float)graphics.GraphicsDevice.Viewport.Width / baseScreenSize.X;

            SpriteScale = Matrix.CreateScale(screenscale, screenscale, 1);

            
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            blockTexture = Content.Load<Texture2D>("block");
            boardBackground = Content.Load<Texture2D>("boardBackground");
            nextPieceBackground = Content.Load<Texture2D>("nextPieceBackground");

            bonuses = new Texture2D[4];
            bonuses[0] = Content.Load<Texture2D>("bonusSingle");
            bonuses[1] = Content.Load<Texture2D>("bonusDouble");
            bonuses[2] = Content.Load<Texture2D>("bonusTriple");
            bonuses[3] = Content.Load<Texture2D>("bonusTetris");

            background = Content.Load<Texture2D>("background");
            background_black = Content.Load<Texture2D>("background_black");

            testFont = Content.Load<SpriteFont>("testFont");

            random = new Random();

            boardPosition = new Vector2(710, 40);            

            bonusQueue = new List<tet_bonus>();

            gameState = tet_constants.STATE_TITLE;                   
        }

        protected override void UnloadContent()
        {
         
        }
  
        protected override void Update(GameTime gameTime)
        {            
            KeyboardState newKeyboardState = Keyboard.GetState();

            if (newKeyboardState.IsKeyDown(Keys.F))
            {
                if (graphics.IsFullScreen == false)
                {
                    graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
                    graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
                    graphics.ApplyChanges();

                    float screenscale = (float)graphics.GraphicsDevice.Viewport.Width / baseScreenSize.X;

                    SpriteScale = Matrix.CreateScale(screenscale, screenscale, 1);

                    this.graphics.ToggleFullScreen();
                }
                else
                {
                    graphics.PreferredBackBufferHeight = 720;
                    graphics.PreferredBackBufferWidth = 1280;
                    graphics.ApplyChanges();

                    float screenscale = (float)graphics.GraphicsDevice.Viewport.Width / baseScreenSize.X;

                    SpriteScale = Matrix.CreateScale(screenscale, screenscale, 1);

                    this.graphics.ToggleFullScreen();
                }
            }

            switch(gameState) {
                case tet_constants.STATE_TITLE:                    
                    if (newKeyboardState.IsKeyDown(Keys.Enter) && oldKeyboardState.IsKeyUp(Keys.Enter))
                    {
                        gameLoop = null;
                        gameLoop = new tet_game_loop();
                        gameState = tet_constants.STATE_PLAYING;
                    }
                    if (newKeyboardState.IsKeyDown(Keys.F1))
                    {                        
                        gameState = tet_constants.STATE_SERVER;
                    }
                    if (newKeyboardState.IsKeyDown(Keys.F2))
                    {                        
                        gameState = tet_constants.STATE_CLIENT;
                    }
                    break;   
                    
                case tet_constants.STATE_PLAYING:                    
                    gameLoop.Update(gameTime);
                    break;                   

                case tet_constants.STATE_GAMEOVER:
                    if (newKeyboardState.IsKeyDown(Keys.Enter) && oldKeyboardState.IsKeyUp(Keys.Enter))
                    {
                        gameLoop = null;
                        //gameLoop = new tet_game_loop();
                        gameState = tet_constants.STATE_TITLE;
                    }
                    break;
                    
                case tet_constants.STATE_PAUSED:
                    if (newKeyboardState.IsKeyDown(Keys.Enter) && oldKeyboardState.IsKeyUp(Keys.Enter))
                        { 
                            gameState = tet_constants.STATE_PLAYING;
                            gameLoop.timer.Enabled = true;
                        }
                    break;
                case tet_constants.STATE_SERVER:
                    server = new tet_net_server();
                    isHost = true;
                    isReady = false;
                    server.netObject.isReady = false;
                    gameState = tet_constants.STATE_LOBBY;
                    break;
                case tet_constants.STATE_CLIENT:
                    client = new tet_net_client();
                    isReady = false;
                    isHost = false;
                    gameState = tet_constants.STATE_LOBBY;
                    break;
                case tet_constants.STATE_LOBBY:
                    if (newKeyboardState.IsKeyDown(Keys.R))
                    {
                        isReady = true;
                    }
                    if (isHost)
                    {
                        if (server.isConnected) server.Update(gameLoop);
                        if (server.netObject.isReady && isReady)
                        {
                            boardPosition.X = 230;
                            gameState = tet_constants.STATE_PLAYING_VS;
                            gameLoop = new tet_game_loop();
                        }
                    }
                    if (!isHost)
                    {
                        if (client.isConnected) client.Update(gameLoop);
                        if (client.netObject.isReady && isReady)
                        {
                            boardPosition.X = 230;
                            gameState = tet_constants.STATE_PLAYING_VS;
                            gameLoop = new tet_game_loop();
                        }
                    }
                    break;
                case tet_constants.STATE_PLAYING_VS:
                    gameLoop.Update(gameTime);
                    if (gameLoop != null)
                    {
                        if (isHost)
                            server.Update(gameLoop);
                        else client.Update(gameLoop);
                    }
                    break;
                case tet_constants.STATE_OP_DISC:                
                case tet_constants.STATE_VS_LOSE:
                case tet_constants.STATE_VS_WON:
                    if (isHost == false)
                    {
                        //if (client != null)
                            //client.Unload();
                        client = null;
                    }
                    else
                    {
                        if (server != null)
                            server.Unload();
                        server = null;
                    }                    
                    gameLoop = null;
                    if (newKeyboardState.IsKeyDown(Keys.Enter) && oldKeyboardState.IsKeyUp(Keys.Enter))
                    {   
                        gameState = tet_constants.STATE_TITLE;
                    }                    
                    break;

            }
            base.Update(gameTime);
            oldKeyboardState = newKeyboardState;
        }

        protected override void Draw(GameTime gameTime)
        {
            Vector3 screenScalingFactor = new Vector3(1, 1, 1);

            Matrix globalTransformation = Matrix.CreateScale(screenScalingFactor);

            GraphicsDevice.Clear(Color.Black);

            //spriteBatch.Begin();
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, SpriteScale);
            

            switch (gameState)
            {
                case tet_constants.STATE_TITLE:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "Press ENTER to play solo.", new Vector2(100, 100), Color.White);
                    spriteBatch.DrawString(testFont, "Press F1 to Host versus.", new Vector2(100, 130), Color.White);
                    spriteBatch.DrawString(testFont, "Press F2 to Join versus.", new Vector2(100, 160), Color.White);  
                    break;
                case tet_constants.STATE_PLAYING:                    
                    gameLoop.Draw(spriteBatch);                    
                    break;
                case tet_constants.STATE_PLAYING_VS:
                    gameLoop.Draw(spriteBatch);
                    drawOpponent(spriteBatch);
                    break;
                case tet_constants.STATE_LOBBY:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "Press R to signal you are ready.", new Vector2(100, 70), Color.White);
                    spriteBatch.DrawString(testFont, "You are ready : " + isReady.ToString(), new Vector2(100, 100), Color.White);
                    if (isHost)
                        spriteBatch.DrawString(testFont, "Opponent is ready : " + server.netObject.isReady.ToString(), new Vector2(100, 130), Color.White);
                    else
                        spriteBatch.DrawString(testFont, "Opponent is ready : " + client.netObject.isReady.ToString(), new Vector2(100, 130), Color.White);
                    break;
                case tet_constants.STATE_GAMEOVER:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "Game over. Press ENTER to return to title.", new Vector2(100, 100), Color.White);
                    break;
                case tet_constants.STATE_PAUSED:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "Game paused. Press ENTER to resume", new Vector2(100, 100), Color.White);
                    break;
                case tet_constants.STATE_OP_DISC:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "Your opponent has disconnected. Press ENTER to return to title.", new Vector2(100, 100), Color.White);
                    break;
                case tet_constants.STATE_VS_LOSE:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "You LOSE. Press ENTER to return to title.", new Vector2(100, 100), Color.White);
                    break;
                case tet_constants.STATE_VS_WON:
                    spriteBatch.Draw(background_black, new Vector2(0, 0), Color.White);
                    spriteBatch.DrawString(testFont, "You WON. Press ENTER to return to title.", new Vector2(100, 100), Color.White);
                    break;

            }

            spriteBatch.DrawString(testFont, "Press F to toggle fullscreen.", new Vector2(20, 1030), Color.White);
            if (gameLoop == null)
            spriteBatch.DrawString(testFont, "null", new Vector2(20, 990), Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }

        private void drawOpponent(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(tet_main.boardBackground, new Vector2(tet_main.boardPosition.X + 940, tet_main.boardPosition.Y - 20), Color.White);

            char[,] matrix;

            if (isHost) matrix = server.netObject.ColorMatrix;
            else matrix = client.netObject.ColorMatrix;

            if(matrix != null)
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 20; j++)
                {
                    switch (matrix[j, i])
                    {
                        case 'j':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Blue);
                            break;
                        case 'i':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Cyan);
                            break;
                        case 's':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Green);
                            break;
                        case 'l':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Orange);
                            break;
                        case 'z':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Purple);
                            break;
                        case 't':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Red);
                            break;
                        case 'o':
                            spriteBatch.Draw(tet_main.blockTexture, new Rectangle((int)tet_main.boardPosition.X + 960 + i * 50, (int)tet_main.boardPosition.Y + j * 50, 50, 50), Color.Yellow);
                            break;
                    }
                }
            }
        }    
    }
}
